﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TestWindowsFormsApplication.Analyzer;
using Model;

namespace TestWindowsFormsApplication
{
    public interface IFreightInfoAnalyse
    {
        /// <summary>
        /// 分析货运数据
        /// </summary>
        /// <param name="orderNo"></param>
        /// <returns></returns>
        FreightInfo Analyse(string orderNo);
        List<FreightInfo> Analyse(List<string> orderNo);
    }

    sealed class FreightInfoAnalyzerFactory
    {
        #region urls
        static List<string> emsUrls = new List<string>();//ems物流网址
        static List<string> dhlUrls = new List<string>();//dhl物流网址
        static List<string> upsUrls = new List<string>();//ups物流网址
        static List<string> tntUrls = new List<string>();//tnt物流网址
        static List<string> dpdUrls = new List<string>();//dpd物流网址
        static List<string> araUrls = new List<string>();//dpd物流网址
        static List<string> ecUrls = new List<string>();//ec物流网址
        static List<string> pxUrls = new List<string>();//4px物流网址
        static List<string> rpxUrls = new List<string>();//rpx物流网址
        static List<string> fedexUrls = new List<string>();//fedex物流网址
        static List<string> ausPostUrls = new List<string>();//fedex物流网址
        #endregion

        static Dictionary<string, IFreightInfoAnalyse> dict = new Dictionary<string, IFreightInfoAnalyse>();
        static Dictionary<string, List<string>> urlsDict = new Dictionary<string, List<string>>();

        static FreightInfoAnalyzerFactory()
        {
            InitTypeChecker();
            InitAnalyzer();
        }

        static void InitAnalyzer()
        {
            dict.Add("ems", new EmsAnalyzer { GetDataUndelived = false });//未妥投也获取数据
            dict.Add("ups", new UpsAnalyzer());
            dict.Add("tnt", new TntAnalyzer());
            dict.Add("dpd", new DpdAnalyzer());
            dict.Add("dpdNew", new DpdNewAnalyzer());
            dict.Add("ara", new AraAnalyzer());
            dict.Add("dhl", new DhlAnalyzer());
            dict.Add("ec", new EcAnalyzer());
            dict.Add("rpx", new RpxAnalyzer());
            dict.Add("fed", new FedexAnalyzer());
            dict.Add("aus", new AusAnalyzer());
            dict.Add("hyexp", new HyexpAnalyzer());
            dict.Add("sgx", new SgxAnalyzer());
            dict.Add("airpak", new FourPXAnalyzer());
            dict.Add("4pxen", new FourPXENAnalyzer());
            dict.Add("usps", new UspsAnalyzer());
            dict.Add("dong", new DongAnalyzer());
            //dict.Add("royal", new RoyalAnalyzer());
            dict.Add("cnexp", new CnexpAnalyzer());
            dict.Add("jsexp", new JsExpENAnalyzer());
            dict.Add("podtrack", new PodtrackAnalyzer());
        }

        static void InitTypeChecker()
        {
            List<string> urls = new List<string>();
            urls.Add(".hyexp.");
            urlsDict.Add("hyexp", urls);

            urlsDict.Add("airpak", new List<string> { "airpak-express" });
            urlsDict.Add("4pxen", new List<string> { "en.4px." });
            urlsDict.Add("sgx", new List<string> { "sgx-th" });

            urlsDict.Add("dpd", dpdUrls);
            dpdUrls.Add("www.dpd.co.uk");

            urlsDict.Add("dpdNew", new List<string> { "www.dpd.com" });

            urlsDict.Add("ara", araUrls);
            araUrls.Add(".aramex.");

            urlsDict.Add("ec", ecUrls);
            ecUrls.Add(".ec-firstclass.");

            //urlsDict.Add("px", pxUrls);
            //pxUrls.Add("4px.com");

            urlsDict.Add("rpx", rpxUrls);
            rpxUrls.Add(".rpxonline.");
            rpxUrls.Add(".rpx.");

            urlsDict.Add("fed", fedexUrls);
            fedexUrls.Add(".fedex.");

            urlsDict.Add("aus", ausPostUrls);
            ausPostUrls.Add("auspost.com");

            #region 17track
            urlsDict.Add("ems", emsUrls);
            emsUrls.Add("ems.com.cn");
            emsUrls.Add("hongkongpost.hk");
            emsUrls.Add(".17track.");
            emsUrls.Add(".flytexpress.");
            emsUrls.Add(".posten.");
            emsUrls.Add(".kuaidi100.");
            emsUrls.Add("intmail.");
            emsUrls.Add(".royalmail.");
            emsUrls.Add(".singpost.");
            emsUrls.Add("tracking.post.japanpost.jp");
            emsUrls.Add(".canadapost.");
            emsUrls.Add(".speedpost.");
            #endregion

            urlsDict.Add("tnt", tntUrls);
            tntUrls.Add("tnt.com");

            urlsDict.Add("dhl", dhlUrls);
            dhlUrls.Add(".dhl.");

            urlsDict.Add("ups", upsUrls);
            upsUrls.Add("www.ups.com");

            urlsDict.Add("usps", new List<string> { ".usps." });
            urlsDict.Add("dong", new List<string> { ".dongbups." });
            //urlsDict.Add("royal", new List<string> { ".royalmail." });
            urlsDict.Add("cnexp", new List<string> { ".cnexps." });
            urlsDict.Add("jsexp", new List<string> { ".js-exp." });
            urlsDict.Add("podtrack", new List<string> { "podtrack" });
        }

        private static bool IsEmsOrderNo(string orderNo)
        {
            if (orderNo == null) { return false; }
            if (orderNo.Length != 13) { return false; }
            if (orderNo.StartsWith("LS", StringComparison.OrdinalIgnoreCase) && orderNo.StartsWith("LS", StringComparison.OrdinalIgnoreCase)) { return false; }
            if (orderNo.StartsWith("WJ", StringComparison.OrdinalIgnoreCase) && orderNo.EndsWith("GB", StringComparison.OrdinalIgnoreCase)) { return false; }
            return orderNo[0] >= 'A' && orderNo[0] <= 'Z' && orderNo[1] >= 'A' && orderNo[1] <= 'Z' &&
                orderNo[11] >= 'A' && orderNo[11] <= 'Z' && orderNo[12] >= 'A' && orderNo[12] <= 'Z';
        }

        private static bool IsUspsOrderNo(string orderNo)
        {
            if (orderNo == null) { return false; }
            if (orderNo.Length != 13) { return false; }
            return orderNo.StartsWith("LS", StringComparison.OrdinalIgnoreCase) && orderNo.EndsWith("CN", StringComparison.OrdinalIgnoreCase);
        }

        private static bool IsDhlOrderNo(string orderNo)
        {
            if (orderNo == null) { return false; }
            if (orderNo.Length < 3) { return false; }
            orderNo = orderNo.ToUpper();
            return orderNo[0] == 'D' && orderNo[0] == 'H' && orderNo[0] == 'L';
        }

        public static IFreightInfoAnalyse Build(string freightCompanyUrl, string orderNo = null)
        {
            IFreightInfoAnalyse analyzer = null;
            freightCompanyUrl = freightCompanyUrl.ToLower();
            if (IsUspsOrderNo(orderNo)) { return dict["usps"]; }
            if (!freightCompanyUrl.Contains("tnt.com") && IsEmsOrderNo(orderNo)) { return dict["ems"]; }
            if (IsDhlOrderNo(orderNo)) { return dict["dhl"]; }
            if (freightCompanyUrl.ToLower().Contains("en.4px.")) { return dict["4pxen"]; }

            var types = urlsDict.Keys.AsEnumerable().ToList();
            foreach (var t in types)
            {
                foreach (string u in urlsDict[t])
                {
                    if (freightCompanyUrl.Contains(u))
                    {
                        return dict[t];
                    }
                }
            }
            return analyzer;
        }
    }

    public sealed class FreightInfoAnalyzer
    {
        public static FreightInfo Analyse(string freightCompanyUrl, string orderNo)
        {
            var analyzer = FreightInfoAnalyzerFactory.Build(freightCompanyUrl, orderNo);
            if (analyzer == null)
            {
                return new FreightInfo { Status = "未查询", ResultText = "" };
            }
            return analyzer.Analyse(orderNo);
        }

        public static bool Is17Track(string freightCompanyUrl, string orderNo)
        {
            var analyzer = FreightInfoAnalyzerFactory.Build(freightCompanyUrl, orderNo);
            if (analyzer == null)
            {
                return false;
            }
            return analyzer is EmsAnalyzer;
        }
    }
}
